﻿using Cuofrisp.Console.MetricInverseProviders;
using Cuofrisp.Console.Simplifiers;
using Cuofrisp.Core.ParallelCore;
using Cuofrisp.Core.ParallelCore.Interfaces;
using MathNet.Symbolics;

namespace Cuofrisp.Console
{
    internal class Program
    {
        private static IExpressionSimplifier? GetSimplifier(StreamReader reader)
        {
            return reader.ReadLine() switch {
                "default" => null,
                "try-all-simplify" => new TryAllSimplifySimplifier(),
                "rational-zero" => new RationalZeroSimplifier(),
                _ => throw new FormatException(
                    "简化器选择不正确（default/try-all-simplify/rational-zero）。")
            };
        }

        private static IMetricInverseProvider? GetMetricInverseProvider(StreamReader reader)
        {
            return reader.ReadLine() switch {
                "default" => null,
                "diagonal" => new DiagonalMetricInverseProvider(),
                "new-bing-generated" => new NewBingGeneratedMetricInverseProvider(),
                "given" => GivenMetricInverseProvider.LoadInverse(reader),
                _ => throw new FormatException(
                    "求逆器选择不正确（default/diagonal/new-bing-generated/given）。")
            };
        }

        internal static void Main()
        {
            using var reader = new StreamReader("input.txt");

            IExpressionSimplifier? simplifier = GetSimplifier(reader);
            IMetricInverseProvider? metricInverseProvider = GetMetricInverseProvider(reader);

            var variables = reader.ReadLine()!
                .Split("\t", StringSplitOptions.RemoveEmptyEntries)
                .Select(i => SymbolicExpression.Parse(i))
                .ToArray();

            var metric = new SymbolicExpression[variables.Length, variables.Length];
            for (int i = 0; i < variables.Length; i++)
            {
                var thisLine = reader.ReadLine()!.Split("\t", StringSplitOptions.RemoveEmptyEntries);
                for (int j = 0; j < variables.Length; j++)
                    metric[i, j] = SymbolicExpression.Parse(thisLine[j]);
            }

            var calculator = new ParallelCuofrispCalculator(simplifier, metricInverseProvider);
            var result = calculator.Calculate(variables, metric);

            using var f = File.Create("output.md");
            new ResultWriter(result).WriteTo(f);
        }
    }
}
